home *** CD-ROM | disk | FTP | other *** search
/ Aminet 24 / Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso / Aminet / comm / mail / Mutt089src.lha / Mutt-0.89i-AMIGA / src / hook.c < prev    next >
C/C++ Source or Header  |  1998-01-28  |  6KB  |  264 lines

  1. /* 
  2.  * Copyright (C) 1996-8 Michael R. Elkins <me@cs.hmc.edu>
  3.  *
  4.  *     This program is free software; you can redistribute it and/or modify
  5.  *     it under the terms of the GNU General Public License as published by
  6.  *     the Free Software Foundation; either version 2 of the License, or
  7.  *     (at your option) any later version.
  8.  *
  9.  *     This program is distributed in the hope that it will be useful,
  10.  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  *     GNU General Public License for more details.
  13.  *
  14.  *     You should have received a copy of the GNU General Public License
  15.  *     along with this program; if not, write to the Free Software
  16.  *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  */
  18.  
  19. #include "mutt.h"
  20. #include "mutt_regex.h"
  21.  
  22. #include <limits.h>
  23. #include <string.h>
  24. #include <stdlib.h>
  25. #include <ctype.h>
  26. #include <unistd.h>
  27.  
  28. typedef struct hook
  29. {
  30.   REGEXP rx;
  31.   char *command;
  32.   struct hook *next;
  33.   int type;
  34. } HOOK;
  35.  
  36. static HOOK *Hooks = NULL;
  37.  
  38. int mutt_parse_hook (const char *s, void *data, char *err, size_t errlen)
  39. {
  40.   HOOK *ptr;
  41.   char expn[LONG_STRING];
  42.   char command[LONG_STRING];
  43.   char pattern[STRING];
  44.   int type = (int) data;
  45.   regex_t *rx;
  46.   int rc, not = 0, flags = 0;
  47.  
  48.   if (*s == '!')
  49.   {
  50.     s++;
  51.     SKIPWS (s);
  52.     not = 1;
  53.   }
  54.  
  55.   s = mutt_extract_token (pattern, sizeof (pattern), s, expn, sizeof (expn), 0);
  56.  
  57.   if (!s)
  58.   {
  59.     strfcpy (err, "too few arguments", errlen);
  60.     return (-1);
  61.   }
  62.  
  63.   s = mutt_extract_token (command, sizeof (command), s, expn, sizeof (expn),
  64.               (type == M_FOLDERHOOK || type == M_SENDHOOK) ?
  65.               (M_SPACE | M_BACKSLASH) : 0);
  66.  
  67.   if (!*command)
  68.   {
  69.     strfcpy (err, "too few arguments", errlen);
  70.     return (-1);
  71.   }
  72.  
  73.   if (s)
  74.   {
  75.     strfcpy (err, "too many arguments", errlen);
  76.     return (-1);
  77.   }
  78.  
  79.   if (type == M_FOLDERHOOK || type == M_MBOXHOOK)
  80.     mutt_expand_path (pattern, sizeof (pattern));
  81.   if (type == M_MBOXHOOK || type == M_SAVEHOOK || type == M_FCCHOOK)
  82.     mutt_expand_path (command, sizeof (command));
  83.  
  84.   /* check to make sure that a matching hook doesn't already exist */
  85.   for (ptr = Hooks; ptr; ptr = ptr->next)
  86.   {
  87.     if (ptr->type == type && ptr->rx.not == not &&
  88.     !strcmp (pattern, ptr->rx.pattern) &&
  89.     !strcmp (command, ptr->command))
  90.       return 0; /* skip it */
  91.     if (!ptr->next)
  92.       break;
  93.   }
  94.  
  95.   if (type == M_SENDHOOK || type == M_SAVEHOOK || type == M_FCCHOOK)
  96.     flags |= REG_ICASE;
  97.  
  98.   rx = safe_malloc (sizeof (regex_t));
  99.  
  100.   if ((rc = REGCOMP (rx, pattern, flags)) != 0)
  101.   {
  102.     regerror (rc, rx, err, errlen);
  103.     regfree (rx);
  104.     safe_free ((void **) &rx);
  105.     return (-1);
  106.   }
  107.  
  108.   if (ptr)
  109.   {
  110.     ptr->next = safe_calloc (1, sizeof (HOOK));
  111.     ptr = ptr->next;
  112.   }
  113.   else
  114.     Hooks = ptr = safe_calloc (1, sizeof (HOOK));
  115.   ptr->type = type;
  116.   ptr->rx.pattern = safe_strdup (pattern);
  117.   ptr->rx.rx = rx;
  118.   ptr->rx.not = not;
  119.   ptr->command = safe_strdup (command);
  120.   return 0;
  121. }
  122.  
  123. void mutt_folder_hook (char *path)
  124. {
  125.   HOOK *tmp = Hooks;
  126.   char err[SHORT_STRING];
  127.  
  128.   for (; tmp; tmp = tmp->next)
  129.     if (tmp->type == M_FOLDERHOOK)
  130.     {
  131.       if ((regexec (tmp->rx.rx, path, 0, NULL, 0) == 0) ^ tmp->rx.not)
  132.       {
  133.     if (mutt_parse_rc_line (tmp->command, err, sizeof (err)) == -1)
  134.     {
  135.       mutt_error ("%s", err);
  136.       sleep (1);    /* pause a moment to let the user see the error */
  137.       return;
  138.     }
  139.       }
  140.     }
  141. }
  142.  
  143. char *mutt_find_hook (int type, const char *pat)
  144. {
  145.   HOOK *tmp = Hooks;
  146.  
  147.   for (; tmp; tmp = tmp->next)
  148.     if (tmp->type == type)
  149.     {
  150.       if (regexec (tmp->rx.rx, pat, 0, NULL, 0) == 0)
  151.     return (tmp->command);
  152.     }
  153.   return (NULL);
  154. }
  155.  
  156. void mutt_send_hook (ADDRESS *addr)
  157. {
  158.   char buf[SHORT_STRING];
  159.   char err[SHORT_STRING];
  160.   ADDRESS *paddr;
  161.   HOOK *hook;
  162.  
  163.   for (hook = Hooks; hook; hook = hook->next)
  164.     if (hook->type == M_SENDHOOK)
  165.       for (paddr = addr; paddr; paddr = paddr->next)
  166.       {
  167.     buf[0] = 0;
  168.     mutt_simple_address (buf, sizeof (buf), paddr);
  169.     if ((regexec (hook->rx.rx, buf, 0, NULL, 0) == 0) ^ hook->rx.not)
  170.     {
  171.       if (mutt_parse_rc_line (hook->command, err, sizeof (err)) != 0)
  172.       {
  173.         mutt_error ("%s", err);
  174.         sleep (1);
  175.         return;
  176.       }
  177.       break;
  178.     }
  179.       }
  180. }
  181.  
  182. static int mutt_addr_hook (char *path, size_t pathlen, int type, ADDRESS *addr)
  183. {
  184.   char buf[SHORT_STRING];
  185.   HOOK *hook;
  186.   ADDRESS *paddr;
  187.  
  188.   for (hook = Hooks; hook; hook = hook->next)
  189.     if (hook->type == type)
  190.       for (paddr = addr; paddr; paddr = paddr->next)
  191.       {
  192.     buf[0] = 0;
  193.     mutt_simple_address (buf, sizeof (buf), paddr);
  194.     if ((regexec (hook->rx.rx, buf, 0, NULL, 0) == 0) ^ hook->rx.not)
  195.     {
  196.       strfcpy (path, hook->command, pathlen);
  197.       return 0;
  198.     }
  199.       }
  200.   return -1;
  201. }
  202.  
  203. void mutt_default_save (char *path, size_t pathlen, ENVELOPE *env)
  204. {
  205.   char tmp[_POSIX_PATH_MAX];
  206.   ADDRESS *adr;
  207.  
  208.   if (mutt_addr_hook (path, pathlen, M_SAVEHOOK, env->from) == 0 ||
  209.       mutt_addr_hook (path, pathlen, M_SAVEHOOK, env->to) == 0 ||
  210.       mutt_addr_hook (path, pathlen, M_SAVEHOOK, env->cc) == 0)
  211.     return;
  212.  
  213.   /* check to see if this is a mailing list */
  214.   for (adr = env->to; adr; adr = adr->next)
  215.     if (mutt_is_mail_list (adr))
  216.       break;
  217.  
  218.   /* check the CC: list */
  219.   if (!adr)
  220.   {
  221.     for (adr = env->cc; adr; adr = adr->next)
  222.       if (mutt_is_mail_list (adr))
  223.     break;
  224.   }
  225.  
  226.   /* pick default based upon sender */
  227.   if (!adr)
  228.   {
  229.     int fromMe = mutt_addr_is_user (env->from);
  230.  
  231.     if (!fromMe && env->reply_to && env->reply_to->mailbox)
  232.       adr = env->reply_to;
  233.     else if (!fromMe && env->from && env->from->mailbox)
  234.       adr = env->from;
  235.     else if (env->to && env->to->mailbox)
  236.       adr = env->to;
  237.     else if (env->cc && env->cc->mailbox)
  238.       adr = env->cc;
  239.   }
  240.  
  241.   mutt_safe_path (tmp, sizeof (tmp), adr);
  242.   snprintf (path, pathlen, "=%s", tmp);
  243. }
  244.  
  245. void mutt_select_fcc (char *path, size_t pathlen, ENVELOPE *env)
  246. {
  247.   ADDRESS *adr;
  248.   char buf[_POSIX_PATH_MAX];
  249.  
  250.   if (mutt_addr_hook (path, pathlen, M_FCCHOOK, env->to) == 0 ||
  251.       mutt_addr_hook (path, pathlen, M_FCCHOOK, env->cc) == 0)
  252.     return;
  253.   if ((option (OPTSAVENAME) || option (OPTFORCENAME)) &&
  254.       (env->to || env->cc || env->bcc))
  255.   {
  256.     adr = env->to ? env->to : (env->cc ? env->cc : env->bcc);
  257.     mutt_safe_path (buf, sizeof (buf), adr);
  258.     snprintf (path, pathlen, "%s/%s", Maildir, buf);
  259.     if (option (OPTFORCENAME) || access (path, W_OK) == 0)
  260.       return;
  261.   }
  262.   strfcpy (path, Outbox, pathlen);
  263. }
  264.